#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;

const u16 crc_ta_4[16]={ /* CRC 半字节余式表 */
    0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
    0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
};

u16 crc_cal_by_halfbyte(const u8 *ptr, u32  len)
{
    u16  crc = 0xffff;
    while(len-->0) {
        u8 high = (u8)(crc >> 12); //暂存CRC的高4位
        crc <<= 4;
        crc ^= crc_ta_4[high^(*ptr>>4)];
        high = (unsigned char)(crc >> 12);
        crc <<= 4;
        crc ^= crc_ta_4[high^(*ptr&0x0f)];
        ptr++;
    }
    return crc;
}

void print_hex(char* name, u8* hex, u16 size)
{
    printf("%s",name);
    printf(": ");
    for(u16 i=0; i<size; i++)
    {
        printf("%02X ", hex[i]);
    }
    printf("\n");
}

//方波的配置
void Generate_Engineering_Mode_Pulse(void)
{
    u8 header[6];
    u8 data[256];
    u16 crc16 = 0;

    u16 para_type_freq = 1000;//频率  1   单位赫兹
    u16 para_type_phase_position = 1;///相位  2   单向（0） 双向（1）
    u16 para_type_current = 20;//电流  3   单位毫安
    u32 para_type_pulse_width = 250;//脉宽       单位微秒
    u16 para_type_provoke_time = 6;///刺激时间    6   单位秒
    u16 para_type_reset_time = 8;//休息时间    7   单位秒
    u16 para_type_work_time = 2;//工作时间    8   单位分
    u16 para_type_waveform = 0;//波形  9   用的是哪种波形, 0,  //方波
    u16 para_type_delay_time = 100;//死区时间    10  正脉冲与负脉冲中间的间隔，单位微秒，范围是（1-255us），默认是0。
    //如果是低8位是0，那么说明不需要后续的半波点值，需要在高8位指定波点值的大小。如果不指定，则使用电流值（参数3）计算出来。
    u8 para_type_half_wave_point_value_count = 0;
    u8 para_type_half_wave_point_value = 0;

    u16 dataLen = 35;

    header[0] = 0xA5;
    header[1] = (u8)dataLen;
    header[2] = dataLen >> 8;
    header[3] = 256 - (header[0] + header[1] + header[2])%256;

    data[0] = 1;//命令，设置工程模式
    data[1] = 11;//参数数量

    data[2] = 1;//频率  1   单位千赫兹
    data[3] = (u8)para_type_freq;
    data[4] = (u8)(para_type_freq >> 8);

    data[5] = 2;//相位
    data[6] = (u8)para_type_phase_position;
    data[7] = (u8)(para_type_phase_position >> 8);

    data[8] = 3;//电流
    data[9] = (u8)para_type_current;
    data[10] = (u8)(para_type_current >> 8);

    data[11] = 4;//脉宽高位
    data[12] = (u8)(para_type_pulse_width >> 16);
    data[13] = (u8)(para_type_pulse_width >> 24);

    data[14] = 5;//脉宽低位
    data[15] = (u8)para_type_pulse_width;
    data[16] = (u8)(para_type_pulse_width >> 8);

    data[17] = 7;//休息时间
    data[18] = (u8)para_type_reset_time;
    data[19] = (u8)(para_type_reset_time >> 8);

    data[20] = 8;//工作时间
    data[21] = (u8)para_type_work_time;
    data[22] = (u8)(para_type_work_time >> 8);

    data[23] = 9;//波形
    data[24] = (u8)para_type_waveform;
    data[25] = (u8)(para_type_waveform >> 8);

    data[26] = 10;//死区时间
    data[27] = (u8)para_type_delay_time;
    data[28] = (u8)(para_type_delay_time >> 8);

    data[29] = 50;//WAVE_POINT_VALUE_COUNT 
    data[30] = para_type_half_wave_point_value_count;
    data[31] = para_type_half_wave_point_value;

    data[32] = 6;//刺激时间
    data[33] = (u8)para_type_provoke_time;
    data[34] = (u8)(para_type_provoke_time >> 8);

    crc16 = crc_cal_by_halfbyte(data,dataLen);

    header[4] = (u8)crc16;
    header[5] = (u8)(crc16 >> 8);

    print_hex("Plus header", header, 6);
    print_hex("data", data,dataLen);
    //A5 23 00 38 D9 61 01 0B 01 E8 03 02 01 00 03 14 00 04 00 00 05 FA 00 07 08 00 08 02 00 09 00 00 0A 64 00 32 00 00 06 06 00
}

//正弦波的配置
void Generate_Engineering_Mode_Sine(void)
{
    u8 header[6];
    u8 data[256];
    u16 crc16 = 0;

    u16 para_type_freq = 1000;//频率  1   单位赫兹，//如果使用频率计算出来的脉宽跟设置下来的脉宽不一致，则使用设置下来的脉宽
    u16 para_type_current = 20;//电流  3   单位毫安
    u32 para_type_pulse_width = 500;//脉宽       单位微秒
    u16 para_type_provoke_time = 6;///刺激时间    6   单位秒
    u16 para_type_reset_time = 8;//休息时间    7   单位秒
    u16 para_type_work_time = 2;//工作时间    8   单位分
    u16 para_type_waveform = 1;//波形  9   用的是哪种波形, 1 正弦波

    u16 dataLen = 26;

    header[0] = 0xA5;
    header[1] = (u8)dataLen;
    header[2] = dataLen >> 8;
    header[3] = 256 - (header[0] + header[1] + header[2])%256;

    data[0] = 1;//命令，设置工程模式
    data[1] = 8;//参数数量

    data[2] = 1;//频率  1   单位千赫兹
    data[3] = (u8)para_type_freq;
    data[4] = (u8)(para_type_freq >> 8);

    data[5] = 3;//电流
    data[6] = (u8)para_type_current;
    data[7] = (u8)(para_type_current >> 8);

    data[8] = 4;//脉宽高位
    data[9] = (u8)(para_type_pulse_width >> 16);
    data[10] = (u8)(para_type_pulse_width >> 24);

    data[11] = 5;//脉宽低位
    data[12] = (u8)para_type_pulse_width;
    data[13] = (u8)(para_type_pulse_width >> 8);

    data[14] = 7;//休息时间
    data[15] = (u8)para_type_reset_time;
    data[16] = (u8)(para_type_reset_time >> 8);

    data[17] = 8;//工作时间
    data[18] = (u8)para_type_work_time;
    data[19] = (u8)(para_type_work_time >> 8);

    data[20] = 9;//波形
    data[21] = (u8)para_type_waveform;
    data[22] = (u8)(para_type_waveform >> 8);

    data[23] = 6;//刺激时间
    data[24] = (u8)para_type_provoke_time;
    data[25] = (u8)(para_type_provoke_time >> 8);

    crc16 = crc_cal_by_halfbyte(data,dataLen);

    header[4] = (u8)crc16;
    header[5] = (u8)(crc16 >> 8);

    print_hex("sine header", header, 6);
    print_hex("data", data,dataLen);
    //A5 1A 00 41 63 45 01 08 01 E8 03 03 14 00 04 00 00 05 F4 01 07 08 00 08 02 00 09 01 00 06 06 00
}

//三角波的配置
void Generate_Engineering_Mode_Triangular(void)
{
    u8 header[6];
    u8 data[256];
    u16 crc16 = 0;

    u16 para_type_freq = 1000;//频率  1   单位赫兹，//如果使用频率计算出来的脉宽跟设置下来的脉宽不一致，则使用设置下来的脉宽
    u16 para_type_current = 30;//电流  3   单位毫安
    u32 para_type_pulse_width = 500;//脉宽       单位微秒
    u16 para_type_provoke_time = 6;///刺激时间    6   单位秒
    u16 para_type_reset_time = 8;//休息时间    7   单位秒
    u16 para_type_work_time = 2;//工作时间    8   单位分
    u16 para_type_waveform = 2;//波形  9   用的是哪种波形, 1 正弦波

    u16 dataLen = 26;

    header[0] = 0xA5;
    header[1] = (u8)dataLen;
    header[2] = dataLen >> 8;
    header[3] = 256 - (header[0] + header[1] + header[2])%256;

    data[0] = 1;//命令，设置工程模式
    data[1] = 8;//参数数量

    data[2] = 1;//频率  1   单位千赫兹
    data[3] = (u8)para_type_freq;
    data[4] = (u8)(para_type_freq >> 8);

    data[5] = 3;//电流
    data[6] = (u8)para_type_current;
    data[7] = (u8)(para_type_current >> 8);

    data[8] = 4;//脉宽高位
    data[9] = (u8)(para_type_pulse_width >> 16);
    data[10] = (u8)(para_type_pulse_width >> 24);

    data[11] = 5;//脉宽低位
    data[12] = (u8)para_type_pulse_width;
    data[13] = (u8)(para_type_pulse_width >> 8);

    data[14] = 7;//休息时间
    data[15] = (u8)para_type_reset_time;
    data[16] = (u8)(para_type_reset_time >> 8);

    data[17] = 8;//工作时间
    data[18] = (u8)para_type_work_time;
    data[19] = (u8)(para_type_work_time >> 8);

    data[20] = 9;//波形
    data[21] = (u8)para_type_waveform;
    data[22] = (u8)(para_type_waveform >> 8);

    data[23] = 6;//刺激时间
    data[24] = (u8)para_type_provoke_time;
    data[25] = (u8)(para_type_provoke_time >> 8);

    crc16 = crc_cal_by_halfbyte(data,dataLen);

    header[4] = (u8)crc16;
    header[5] = (u8)(crc16 >> 8);

    print_hex("Triangular header", header, 6);
    print_hex("data", data,dataLen);
    //A5 1A 00 41 6E 7D 01 08 01 E8 03 03 1E 00 04 00 00 05 F4 01 07 08 00 08 02 00 09 02 00 06 06 00
}

void Generate_Execute_Mode(void)
{
    u8 header[6];
    u8 data[256];
    u16 crc16 = 0;

    u16 dataLen = 8;

    header[0] = 0xA5;
    header[1] = (u8)dataLen;
    header[2] = dataLen >> 8;
    header[3] = 256 - (header[0] + header[1] + header[2])%256;

    data[0] = 7;//命令，执行模式    7
    data[1] = 2;

    data[2] = 30;//PARA_TYPE_MODE = 30,//模式    30  波输出所属模式
    data[3] = 0;//（小端低位）0是工程模式
    data[4] = 0;//（小端高位）0是工程模式

    data[5] = 32;//PARA_TYPE_EXECUTED_TYPE = 32,//    1开始该模式，2停止该模式
    data[6] = 1;
    data[7] = 0;

    crc16 = crc_cal_by_halfbyte(data,dataLen);

    header[4] = (u8)crc16;
    header[5] = (u8)(crc16 >> 8);

    print_hex("execute header", header, 6);
    print_hex("data", data,dataLen);
    //开始 A5 08 00 53 15 B9 07 02 1E 00 00 20 01 00
    //停止 A5 08 00 53 46 EC 07 02 1E 00 00 20 02 00
}

void Generate_Read_Existing_Mode_Config(void)
{
    u8 header[6];
    u8 data[256];
    u16 crc16 = 0;

    u16 dataLen = 5;

    header[0] = 0xA5;
    header[1] = (u8)dataLen;
    header[2] = dataLen >> 8;
    header[3] = 256 - (header[0] + header[1] + header[2])%256;

    data[0] = 9;//命令，读取配置
    data[1] = 1;//参数数量

    data[2] = 30;//PARA_TYPE_MODE = 30,//模式    30  波输出所属模式
    data[3] = 0;//（小端低位）0是工程模式
    data[4] = 0;//（小端高位）0是工程模式

    crc16 = crc_cal_by_halfbyte(data,dataLen);

    header[4] = (u8)crc16;
    header[5] = (u8)(crc16 >> 8);

    print_hex("Read Existing Mode Config header", header, 6);
    print_hex("data", data,dataLen);
    //A5 05 00 56 A6 97 09 01 1E 00 00
}

void Generate_Execute_Mode_For_NS4(void)
{
    u8 header[6];
    u8 data[256];
    u16 crc16 = 0;

    u16 dataLen = 11;
    u16 para_type_current = 20;//电流  3   单位毫安

    header[0] = 0xA5;
    header[1] = (u8)dataLen;
    header[2] = dataLen >> 8;
    header[3] = 256 - (header[0] + header[1] + header[2])%256;

    data[0] = 7;//命令，执行模式    7
    data[1] = 3;

    data[2] = 30;//PARA_TYPE_MODE = 30,//模式    30  波输出所属模式
    data[3] = 5;//（小端低位）模式
    data[4] = 0;//（小端高位）模式

    data[5] = 32;//PARA_TYPE_EXECUTED_TYPE = 32,//    1开始该模式，2停止该模式
    data[6] = 1;
    data[7] = 0;

    data[8] = 3;//电流, 此参数可选
    data[9] = (u8)para_type_current;
    data[10] = (u8)(para_type_current >> 8);

    crc16 = crc_cal_by_halfbyte(data,dataLen);

    header[4] = (u8)crc16;
    header[5] = (u8)(crc16 >> 8);

    print_hex("ns4 execute header", header, 6);
    print_hex("data", data,dataLen);
    //开始 A5 0B 00 50 F4 2D 07 03 1E 05 00 20 01 00 03 14 00
    //停止 A5 0B 00 50 26 C3 07 03 1E 05 00 20 02 00 03 14 00
}

void Generate_Set_New_Mode_Pulse(void)
{
    u8 header[6];
    u8 data[256];
    u16 crc16 = 0;

    u16 para_type_freq = 1000;//频率  1   单位赫兹
    u16 para_type_phase_position = 1;///相位  2   单向（0） 双向（1）
    u16 para_type_current = 20;//电流  3   单位毫安
    u32 para_type_pulse_width = 250;//脉宽       单位微秒
    u16 para_type_provoke_time = 6;///刺激时间    6   单位秒
    u16 para_type_reset_time = 8;//休息时间    7   单位秒
    u16 para_type_work_time = 2;//工作时间    8   单位分
    u16 para_type_waveform = 0;//波形  9   用的是哪种波形, 0,  //方波
    u16 para_type_delay_time = 100;//死区时间    10  正脉冲与负脉冲中间的间隔，单位微秒，范围是（1-255us），默认是0。
    //如果是低8位是0，那么说明不需要后续的半波点值，需要在高8位指定波点值的大小。如果不指定，则使用电流值（参数3）计算出来。
    u8 para_type_half_wave_point_value_count = 0;
    u8 para_type_half_wave_point_value = 0;

    u16 dataLen = 38;

    header[0] = 0xA5;
    header[1] = (u8)dataLen;
    header[2] = dataLen >> 8;
    header[3] = 256 - (header[0] + header[1] + header[2])%256;

    data[0] = 3;//命令，设置新模式
    data[1] = 12;//参数数量

    data[2] = 1;//频率  1   单位千赫兹
    data[3] = (u8)para_type_freq;
    data[4] = (u8)(para_type_freq >> 8);

    data[5] = 2;//相位
    data[6] = (u8)para_type_phase_position;
    data[7] = (u8)(para_type_phase_position >> 8);

    data[8] = 3;//电流
    data[9] = (u8)para_type_current;
    data[10] = (u8)(para_type_current >> 8);

    data[11] = 4;//脉宽高位
    data[12] = (u8)(para_type_pulse_width >> 16);
    data[13] = (u8)(para_type_pulse_width >> 24);

    data[14] = 5;//脉宽低位
    data[15] = (u8)para_type_pulse_width;
    data[16] = (u8)(para_type_pulse_width >> 8);

    data[17] = 7;//休息时间
    data[18] = (u8)para_type_reset_time;
    data[19] = (u8)(para_type_reset_time >> 8);

    data[20] = 8;//工作时间
    data[21] = (u8)para_type_work_time;
    data[22] = (u8)(para_type_work_time >> 8);

    data[23] = 9;//波形
    data[24] = (u8)para_type_waveform;
    data[25] = (u8)(para_type_waveform >> 8);

    data[26] = 10;//死区时间
    data[27] = (u8)para_type_delay_time;
    data[28] = (u8)(para_type_delay_time >> 8);

    data[29] = 50;//WAVE_POINT_VALUE_COUNT 
    data[30] = para_type_half_wave_point_value_count;
    data[31] = para_type_half_wave_point_value;

    data[32] = 6;//刺激时间
    data[33] = (u8)para_type_provoke_time;
    data[34] = (u8)(para_type_provoke_time >> 8);

    data[35] = 30;//PARA_TYPE_MODE = 30,//模式    30  波输出所属模式
    data[36] = 1;//（小端低位）模式1
    data[37] = 0;//（小端高位）模式1

    crc16 = crc_cal_by_halfbyte(data,dataLen);

    header[4] = (u8)crc16;
    header[5] = (u8)(crc16 >> 8);

    print_hex("set new mode header", header, 6);
    print_hex("data", data,dataLen);
    //A5 26 00 35 13 5C 03 0C 01 E8 03 02 01 00 03 14 00 04 00 00 05 FA 00 07 08 00 08 02 00 09 00 00 0A 64 00 32 00 00 06 06 00 1E 01 00
}

int main(void)
{
    Generate_Engineering_Mode_Pulse();
    Generate_Engineering_Mode_Sine();
    Generate_Engineering_Mode_Triangular();
    Generate_Execute_Mode();
    Generate_Read_Existing_Mode_Config();
    Generate_Execute_Mode_For_NS4();
    Generate_Set_New_Mode_Pulse();
    return 0;
}

